/**
 * 发布订阅模式
 */
class EventEmitter {
  // 用于保存所有的事件及回调映射
  // 如: listeners.click = [() => {}, () => {}]
  // listeners.keydown = [() => {}, () => {}, () => {}]
  // 对象属性名为事件类型名称，属性值为数组（用于保存事件的回调函数）
  private listeners: Record<string, Function[]> = {}

  /**
   * 订阅，注册事件监听
   */
  on(type: string, callback: Function) {
    // 是否在 listeners 中已存在当前注册类型的事件属性，
    // 如果存在，则将回调追加，如果不存在，则新增一项事件属性
    const has = this.listeners[type]
    if (has) {
      has.push(callback)
    } else {
      this.listeners[type] = [ callback ]
    }
  }

  /**
   * 发布，触发事件
   */
  emit(type: string, ...args: any[]) {
    // 是否存在
    const has = this.listeners[type]
    // has 是一个数组，数组中保存的每个元素是回调函数
    if (has) {
      has.forEach(callback => {
        callback(...args)
      })
    }
  }

  /**
   * 移除事件监听
   */
  off(type: string, callback: Function) {
    // 是否存在
    const has = this.listeners[type]
    if (has) {
      // 如果有传递移除的回调函数，则仅移除指定回调
      if (callback) {
        this.listeners[type] = has.filter(cb => cb !== callback)
      } else {
        this.listeners[type] = []
      }
    }
  }
}

export const emitter = new EventEmitter()
